namespace cpputils
{

template<class T>
struct smart_ptr
{
public:
	explicit smart_ptr(T* V = 0)
		: Ptr(V)
	{
	}
	smart_ptr(const smart_ptr<T>& V)
		: Ptr(V.release())
	{
	}
	template<class T2>
	smart_ptr(const smart_ptr<T2>& V)
		: Ptr(V.release())
	{
	}
	smart_ptr<T>& operator=(const smart_ptr<T>& V)
	{
		reset(V.release());
		return *this;
	}
	template<class T2>
	smart_ptr<T>& operator=(const smart_ptr<T2>& V)
	{
		reset(V.release());
		return *this;
	}
	~smart_ptr()
	{
		delete Ptr;
	}
	T& operator*() const
	{
		return *Ptr;
	}
	T* operator->() const
	{
		return Ptr;
	}
	T* get() const
	{
		return Ptr;
	}
	T* release() const
	{
		T* Temp = Ptr;
		Ptr = 0;
		return Temp;
	}
	void reset(T* V = 0)
	{
		if (V != Ptr) delete Ptr;
		Ptr = V;
	}
private:
	mutable T* Ptr;
};

template<class T>
inline smart_ptr<T> make_smart_ptr(T* V)
{
	return smart_ptr<T>(V);
}

template<class TT, class T>
inline smart_ptr<TT> dynamic_convert(const smart_ptr<T>& Val)
{
	if (Val.get() == 0) return smart_ptr<TT>(0);
	TT* Ptr = &dynamic_cast<TT&>(*Val);
	Val.release();
	return smart_ptr<TT>(Ptr);
}

}
